#pragma once
#include <grpcpp/grpcpp.h>
#include <json/json.h>
#include <json/value.h>
#include <json/reader.h>
#include "message.grpc.pb.h"
#include "message.pb.h"
#include "const.h"
#include "Singleton.h"
#include <queue>
#include <memory>
#include <condition_variable>


using grpc::Channel;
using grpc::Status;
using grpc::ClientContext;

using message::GetVerifyCodeRequest;
using message::GetVerifyCodeResponse;


class RPConPool {
public:
    RPConPool(std::size_t poolSize,std::string host,std::string port)
    :poolSize_(poolSize),host_(host),port_(port),b_stop_(false)
    {
        //初始化连接
        for(int i=0;i<poolSize;i++)
        {
            connections_.push(message::VerifyCode::NewStub(
                                            grpc::CreateChannel(host_+":"+port_,
                                            grpc::InsecureChannelCredentials())
                                        ));
        }

    }


    ~RPConPool()
    {
        std::unique_lock<std::mutex> lck(mtx_);
        Close();
        while (!connections_.empty())
        {
            connections_.pop();
        }
        std::cout<<"RPConPool::~RPConPool()"<<std::endl;
    }
    void Close()
    {
        b_stop_=true;
        cond_.notify_all();
    }

    //获取连接
    std::unique_ptr<message::VerifyCode::Stub> GetConnection()
    {
        std::unique_lock<std::mutex> lock(mtx_);
        
        cond_.wait(lock,[this](){
            return !connections_.empty() || b_stop_;
        });
        if(b_stop_)
        {
            return nullptr;
        }
        auto conn = std::move(connections_.front());
        connections_.pop();
        return conn;
    }

    //归还连接
    void ReturConnection(std::unique_ptr<message::VerifyCode::Stub> stub)
    {
        std::unique_lock<std::mutex> lock(mtx_);
        if (b_stop_)
        {
            return;
        }
        connections_.push(std::move(stub));
        cond_.notify_one();
        
    }



private:
    bool b_stop_;
    std::size_t poolSize_;
    std::mutex mtx_;
    std::queue<std::unique_ptr<message::VerifyCode::Stub>> connections_;
    std::condition_variable cond_;

    std::string host_;
    std::string port_;
};






















class VerifyGrpcClient: public Singleton<VerifyGrpcClient>
{
    friend class Singleton<VerifyGrpcClient>;
public:
    ~VerifyGrpcClient() = default;
    GetVerifyCodeResponse GetVerifyCode(std::string email);


private:
    VerifyGrpcClient();
    std::unique_ptr<RPConPool> pool_;


};


